<?php
/**
 * Fuehrt eine Ueberpruefung der Personalausweisnummer durch
 * 
 * @author		Joachim Ruf
 * @copyright	Copyright (c) 2003-2013 Loresoft Software (http://www.loresoft.de)
 * @license		http://yapary.loresoft.de/lizenzbedingungen     New BSD License
 * 
 * */


Class Yapary_Other_Passport
{	

	
	function __construct ( )
	{
	}
	
	
	/**
	* Berechnet anhand der Eingabe $sign die Prüfziffer.
	* @param int $sign : Zahlenfolge für welche die Prüfziffer berechnet werden soll
	* @return int|NULL
	*/
	public function getChecksum( $sign )
	{
		if( !is_numeric($sign) )
			return NULL;
		if( strlen($sign) == 0 )
			return NULL;

		
		$arrRandom = array(7, 3, 1);	// Zahlenkombinationen für Modulo-Rechnung
		$checksum = 0;

		// Checksumme erstellen
		$len = strlen($sign);
		for( $i=0; $i<=$len; $i++ )
			$checksum += substr($sign, $i, 1) * $arrRandom[$i%3];

		return ($checksum%10);
	}	
	
	
	/**
	* Berechnet anhand der Grunddaten eine Personalausweisnummer.
	* Liefert bei Erfolgsfall ein Array der Größe 4 mit den Daten zurück
	* @param int $sign : 4-Stellige Behördenkennzahl
	* @param date $birthday : Geburtstag im Format YYYY-MM-DD
	* @param date $expire : Gültig bis... im Format YYYY-MM-DD
	* @return string|NULL
	*/
	public function create ( $sign, $birthday, $expire, $separator = '-' )
	{
		$arr = array(NULL, NULL, NULL, NULL); // Speicherung der einzelnen Prüfziffern


		if( !(is_numeric($sign) && strlen($sign) == 4) )
			return NULL;
		if( !preg_match("/^\d{4}-\d{2}-\d{2}$/", $birthday) )
			return NULL;
		if( !preg_match("/^\d{4}-\d{2}-\d{2}$/", $expire) )
			return NULL;
		
			
		// Generiere Nummer für Erstwohnsitz
		$tmp = $sign.rand(11111, 99999); // bei 00001-99999 wird ab und an Fehler erzeugt, da ein Zeichen fehlt! bei 11111-99999 klappt alles wunderbar
		$tmp .= self::getChecksum($tmp);
		$arr[0] = $tmp.'D';
		
		// Generiere Nummer für Geburtsdatum
		$arr[1] = $birthday{2}.$birthday{3} . $birthday{5}.$birthday{6} . $birthday{8}.$birthday{9};
		$arr[1] .= self::getChecksum($arr[1]);

		// Generiere Nummer für Ablaufdatum
		$arr[2] = $expire{2}.$expire{3} . $expire{5}.$expire{6} . $expire{8}.$expire{9};
		$arr[2] .= self::getChecksum($arr[2]);
		
		// Generiere Checksumme für gesamte Daten		
		$arr[3] = self::getChecksum($tmp.$arr[1].$arr[2]);

		
		return $arr[0].$separator.$arr[1].$separator.$arr[2].$separator.$arr[3];
	}	
	
	
	/**
	* Führt eine einfache Überprüfung durch, ob die eingegebene Personalausweisummer gültig ist.
	* Beachtet bei der Überprüfung nicht, ob das Datum noch gültig ist!
	* @param string $persSign1 : 11-Stellige Zahlenfolge (Behördenkennzahlinformation)
	* @param int $persSign2 : 7-Stellige Zahlenfolge (Geburtsdatum + Checksumme)
	* @param int $persSign3 : 7-Stellige Zahlenfolge (Gültigkeit + Checksumme)
	* @param int $persSign4 : 1-Stellige Zahlenfolge (Überprüft alle Eingaben)
	* @return bool
	*/
	public function verify ( $persSign1, $persSign2, $persSign3, $persSign4 )
	{
		/*
		* persSign1 1-10  : nur Zahlen gültig
		* persSign1 11    : ein einzelnes Zeichen
		* persSign2-sign4 : nur Zahlen gültig
		*/
		$date = date("ymd");


		// Formatkorrektheit pruefen
		if( !(is_string($persSign1) && strlen($persSign1) == 11) )
			return false;
		if( !(is_numeric($persSign2) && strlen($persSign2) == 7) )
			return false;
		if( !(is_numeric($persSign3) && strlen($persSign3) == 7) )
			return false;
		if( !(is_numeric($persSign4) && strlen($persSign4) == 1) )
			return false;			

		 // Pruefen ob Ausweis abgelaufen ist
		if( substr($persSign3, 0, 6) <= $date )
			return false;
		
		
		// === Abgleich der Berechneten Checksummen mit den übergebenen Checksummen ===
		if(
			self::getChecksum(substr($persSign1, 0, 9)) == substr($persSign1, 9, 1) &&
			self::getChecksum(substr($persSign2, 0, 6)) == substr($persSign2, 6, 1) &&
			self::getChecksum(substr($persSign3, 0, 6)) == substr($persSign3, 6, 1) &&
			self::getChecksum(substr($persSign1, 0, 10).substr($persSign2, 0, 7).substr($persSign3, 0, 7) ) == $persSign4
		)
		return true; // Checksummen OK

	
		return false;
	}

	
	/**
	* Gleicht eine Personalausweisnummer mit dem Geburtsdatum ab
	* Prüft zusätzlich noch, ob der Ausweis noch gültig- oder abgelaufen ist.
	* @param string $persSign1 : 11-Stellige Zahlenfolge (Behördenkennzahlinformation)
	* @param int $persSign2 : 7-Stellige Zahlenfolge (Geburtsdatum + Checksumme)
	* @param int $persSign3 : 7-Stellige Zahlenfolge (Gültigkeit + Checksumme)
	* @param int $persSign4 : 1-Stellige Zahlenfolge (Überprüft alle Eingaben)
	* @param date $birthday : Geburtstag im Format YYYY-MM-DD
	* @return bool
	*/
	public function verifyByBirthday ( $persSign1, $persSign2, $persSign3, $persSign4, $birthday )
	{
		if( !self::verify($persSign1, $persSign2, $persSign3, $persSign4) ) // Wenn nicht allgemein Gültig
			return false;

		if( !preg_match("/^\d{4}-\d{2}-\d{2}$/", $birthday) )
			return false;

		// Geburtsdatum pruefen
		if( substr($persSign2, 0, 6) != $birthday{2}.$birthday{3} . $birthday{5}.$birthday{6} . $birthday{8}.$birthday{9} ) // Wenn Geburtsdatum nicht übereinstimmt
			return false;

		
		return true;
	}
	

}





/*
	Personalausweisnummerdaten
	
	731731731    731731  731731
	*********    ******  ******
	wwwwNNNNNpD--yyMMddX-YYmmDDx-------n 
	|||||||||||  ||||||| |||||||       |
	|||||||||||  ||||||| |||||||       -__ Prüfsumme ALLER Ziffern
	|||||||||||  ||||||| |||||||
	|||||||||||  ||||||| ||||||-__ Prüfsumme Ablaufdatum
	|||||||||||  ||||||| ||||--__ Ablaufdatum Tag
	|||||||||||  ||||||| ||--__ Ablaufdatum Monat
	|||||||||||  ||||||| --__ Ablaufdatum Jahr
	|||||||||||  |||||||
	|||||||||||  ||||||-__ Prüfsumme Geb.-Datum
	|||||||||||  ||||--__ Geb.-Tag
	|||||||||||  ||--__ Geb.-Monat
	|||||||||||  --__ Geb.-Jahr
	|||||||||||
	|||||||||| __ Staatszugehörigkeit D = Deutsch
	||||||||| __ Prüfsumme für wwwwNNNNN
	||||-----__ laufende Zählnummer
	----__ Erstwohnsitz Kennzahl
*/



?>